home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / C / LIB / UNIXLIB37B / !UnixLib37 / src / time / c / setitmr < prev    next >
Text File  |  1996-11-09  |  4KB  |  151 lines

  1. /****************************************************************************
  2.  *
  3.  * $Source: /unixb/home/unixlib/source/unixlib37/src/time/c/RCS/setitmr,v $
  4.  * $Date: 1996/10/30 21:59:01 $
  5.  * $Revision: 1.3 $
  6.  * $State: Rel $
  7.  * $Author: unixlib $
  8.  *
  9.  * $Log: setitmr,v $
  10.  * Revision 1.3  1996/10/30 21:59:01  unixlib
  11.  * Massive changes made by Nick Burret and Peter Burwood.
  12.  *
  13.  * Revision 1.2  1996/05/06 09:01:35  unixlib
  14.  * Updates to sources made by Nick Burrett, Peter Burwood and Simon Callan.
  15.  * Saved for 3.7a release.
  16.  *
  17.  * Revision 1.1  1996/04/19 21:35:00  simon
  18.  * Initial revision
  19.  *
  20.  ***************************************************************************/
  21.  
  22. static const char rcs_id[] = "$Id: setitmr,v 1.3 1996/10/30 21:59:01 unixlib Rel $";
  23.  
  24. #include <stddef.h>
  25. #include <errno.h>
  26. #include <sys/os.h>
  27. #include <sys/swis.h>
  28. #include <sys/time.h>
  29. #include <sys/unix.h>
  30. #include <sys/syslib.h>
  31.  
  32. /* setitimer provides a mechanism for a process to interrupt itself at
  33.    some future time. This is achieved by setting a timer; when the
  34.    timer expires, the process receives a signal.
  35.  
  36.    Each process has three independent interval timers available:
  37.  
  38.    ITIMER_REAL: A real-time timer that counts clock time. This timer
  39.    sends a SIGALRM signal to the process when it expires.
  40.  
  41.    ITIMER_VIRTUAL: A virtual timer that counts CPU time used by the
  42.    process. This timer sends a SIGVTALRM signal to the process when it
  43.    expires.
  44.  
  45.    ITIMER_PROF: A profiling timer that counts both CPU time used by
  46.    the process, and CPU time spent in systems calls on behalf of the
  47.    process. This timer sends a SIGPROF signal to the process when it
  48.    expires.
  49.  
  50.    Only one timer of each kind can be set at any given time. If a timer
  51.    is set that has not yet expired, that timer is reset to the new value.
  52.  
  53.    The setitimer function sets the timer specified by WHICH
  54.    according to NEW.  The WHICH argument can have a value of
  55.    ITIMER_REAL, ITIMER_VIRTUAL, or ITIMER_PROF.
  56.  
  57.    If OLD is not a null pointer, setitimer returns information
  58.    about any previous unexpired timer of the same kind in the
  59.    structure it points to.
  60.  
  61.    The return value is 0 on success and -1 on failure.  */
  62.  
  63. typedef void (*ticker) (void);
  64.  
  65. static void
  66. remove_ticker (ticker address, struct timeval *old)
  67. {
  68.   int regs[10];
  69.  
  70.   regs[0] = (int) address;
  71.   regs[1] = (int) old;
  72.   os_swi (OS_RemoveTickerEvent, regs);
  73. }
  74.  
  75. static int
  76. add_ticker (struct timeval *time, ticker address, struct timeval *new)
  77. {
  78.   int regs[10];
  79.  
  80.   regs[0] = (int) (time->tv_sec * 100) + time->tv_usec;
  81.   regs[1] = (int) address;
  82.   regs[2] = (int) new;
  83.   return os_swi (OS_CallAfter, regs) ? -1 : 0;
  84. }
  85.  
  86. static int
  87. check_ticker (struct timeval *time)
  88. {
  89.   if (time->tv_sec > 0 || time->tv_usec > 0)
  90.     return 1;
  91.   if (time->tv_sec == 0 && time->tv_usec == 0)
  92.     return 2;
  93.   return 0;
  94. }
  95.  
  96. struct timer_control
  97.   {
  98.     ticker  callback;
  99.     int    *sema;
  100.   };
  101.  
  102. static struct timer_control timer_controls[__MAX_ITIMERS] =
  103.   {
  104.     {__h_sigalrm_init, &__h_sigalrm_sema},         /* ITIMER_REAL */
  105.     {__h_sigvtalrm_init, &__h_sigvtalrm_sema},     /* ITIMER_VIRTUAL */
  106.     {__h_sigprof_init, &__h_sigprof_sema}          /* ITIMER_PROF */
  107.   };
  108.  
  109. int
  110. setitimer (enum __itimer_which which, struct itimerval *new_timer,
  111.        struct itimerval *old_timer)
  112. {
  113.   struct itimerval *itimer;
  114.  
  115.   /* We can't implement interval timers whilst executing in a task
  116.      window.  */
  117.   if (__taskwindow)
  118.     {
  119.       errno = ENOSYS;
  120.       return -1;
  121.     }
  122.  
  123.   if ((unsigned)which >= __MAX_ITIMERS)
  124.     {
  125.       errno = EINVAL;
  126.       return -1;
  127.     }
  128.  
  129.   /* __u is current process <sys/unix.h>.  */
  130.   itimer = &__u->itimers[which];
  131.   if (old_timer)
  132.     *old_timer = *itimer;
  133.  
  134.   /* Only if a timer is already active (it_value > 0), then remove it */
  135.   if ((check_ticker (&itimer->it_value) == 1)
  136.       || check_ticker (&itimer->it_interval))
  137.     {
  138.       remove_ticker (timer_controls[which].callback, &itimer->it_interval);
  139.       *(timer_controls[which].sema) = 0;
  140.     }
  141.  
  142.   *itimer = *new_timer;
  143.  
  144.   if (check_ticker (&new_timer->it_value) == 1)
  145.     return add_ticker (&new_timer->it_value,
  146.                        timer_controls[which].callback,
  147.                        &itimer->it_interval);
  148.  
  149.   return 0;
  150. }
  151.